<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>⚡ N8N Workflow Documentation</title>
  <script src="https://cdn.jsdelivr.net/npm/mermaid@10.6.1/dist/mermaid.min.js"></script>
  <style>
    /* Modern CSS Reset and Base */
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    :root {
      --primary: #3b82f6;
      --primary-dark: #2563eb;
      --success: #10b981;
      --warning: #f59e0b;
      --error: #ef4444;
      --bg: #ffffff;
      --bg-secondary: #f8fafc;
      --bg-tertiary: #f1f5f9;
      --text: #1e293b;
      --text-secondary: #64748b;
      --text-muted: #94a3b8;
      --border: #e2e8f0;
      --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
      --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
    }

    [data-theme="dark"] {
      --bg: #0f172a;
      --bg-secondary: #1e293b;
      --bg-tertiary: #334155;
      --text: #f8fafc;
      --text-secondary: #cbd5e1;
      --text-muted: #64748b;
      --border: #475569;
    }

    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      background: var(--bg);
      color: var(--text);
      line-height: 1.6;
      transition: all 0.2s ease;
    }

    .container {
      max-width: 1200px;
      margin: 0 auto;
      padding: 0 1rem;
    }

    /* Header */
    .header {
      background: var(--bg-secondary);
      border-bottom: 1px solid var(--border);
      padding: 2rem 0;
      text-align: center;
    }

    .title {
      font-size: 2.5rem;
      font-weight: 700;
      margin-bottom: 0.5rem;
      color: var(--primary);
    }

    .subtitle {
      font-size: 1.125rem;
      color: var(--text-secondary);
      margin-bottom: 2rem;
    }

    .stats {
      display: flex;
      gap: 2rem;
      justify-content: center;
      flex-wrap: wrap;
    }

    .stat {
      text-align: center;
      min-width: 100px;
    }

    .stat-number {
      display: block;
      font-size: 1.875rem;
      font-weight: 700;
      color: var(--primary);
    }

    .stat-label {
      font-size: 0.875rem;
      color: var(--text-muted);
      text-transform: uppercase;
      letter-spacing: 0.05em;
    }

    /* Controls */
    .controls {
      background: var(--bg);
      border-bottom: 1px solid var(--border);
      padding: 1.5rem 0;
      position: sticky;
      top: 0;
      z-index: 100;
    }

    .search-section {
      display: flex;
      align-items: center;
      gap: 1rem;
      margin-bottom: 1rem;
    }

    .search-input {
      flex: 1;
      padding: 0.75rem 1rem;
      border: 1px solid var(--border);
      border-radius: 0.5rem;
      background: var(--bg);
      color: var(--text);
      font-size: 1rem;
      min-width: 300px;
    }

    .search-input:focus {
      outline: none;
      border-color: var(--primary);
      box-shadow: 0 0 0 3px rgb(59 130 246 / 0.1);
    }

    .filter-section {
      display: flex;
      align-items: center;
      gap: 1rem;
      flex-wrap: wrap;
    }

    .filter-group {
      display: flex;
      align-items: center;
      gap: 0.5rem;
    }

    .filter-group label {
      font-size: 0.875rem;
      font-weight: 500;
      color: var(--text-secondary);
    }

    .filter-group select {
      padding: 0.5rem;
      border: 1px solid var(--border);
      border-radius: 0.375rem;
      background: var(--bg);
      color: var(--text);
      font-size: 0.875rem;
    }

    .theme-toggle {
      background: var(--bg-tertiary);
      border: 1px solid var(--border);
      border-radius: 0.5rem;
      padding: 0.5rem 1rem;
      cursor: pointer;
      font-size: 1rem;
      margin-left: auto;
    }

    .results-info {
      margin-top: 1rem;
      font-size: 0.875rem;
      color: var(--text-secondary);
    }

    /* Main Content */
    .main {
      padding: 2rem 0;
    }

    /* States */
    .state {
      text-align: center;
      padding: 4rem 2rem;
    }

    .state .icon {
      font-size: 4rem;
      margin-bottom: 1rem;
    }

    .state h3 {
      font-size: 1.5rem;
      margin-bottom: 0.5rem;
      color: var(--text);
    }

    .state p {
      color: var(--text-secondary);
      margin-bottom: 2rem;
    }

    .retry-btn {
      background: var(--primary);
      color: white;
      border: none;
      padding: 0.75rem 1.5rem;
      border-radius: 0.5rem;
      cursor: pointer;
      font-size: 1rem;
      font-weight: 500;
    }

    .retry-btn:hover {
      background: var(--primary-dark);
    }

    /* Workflow Grid */
    .workflow-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
      gap: 1.5rem;
    }

    .workflow-card {
      background: var(--bg-secondary);
      border: 1px solid var(--border);
      border-radius: 0.75rem;
      padding: 1.5rem;
      box-shadow: var(--shadow);
      transition: all 0.2s ease;
      cursor: pointer;
      position: relative;
    }

    .workflow-card:hover {
      box-shadow: var(--shadow-lg);
      border-color: var(--primary);
      transform: translateY(-2px);
    }

    .workflow-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: 1rem;
    }

    .workflow-meta {
      display: flex;
      align-items: center;
      gap: 0.5rem;
      font-size: 0.875rem;
      color: var(--text-secondary);
    }

    .status-dot {
      width: 8px;
      height: 8px;
      border-radius: 50%;
    }

    .status-active {
      background: var(--success);
    }

    .status-inactive {
      background: var(--text-muted);
    }

    .complexity-dot {
      width: 8px;
      height: 8px;
      border-radius: 50%;
    }

    .complexity-low {
      background: var(--success);
    }

    .complexity-medium {
      background: var(--warning);
    }

    .complexity-high {
      background: var(--error);
    }

    .trigger-badge {
      background: var(--primary);
      color: white;
      padding: 0.25rem 0.5rem;
      border-radius: 0.375rem;
      font-size: 0.75rem;
      font-weight: 500;
    }

    .category-badge {
      background: var(--bg-tertiary);
      color: var(--text-secondary);
      padding: 0.125rem 0.375rem;
      border-radius: 0.25rem;
      font-size: 0.75rem;
      border: 1px solid var(--border);
      font-weight: 500;
    }

    .workflow-title {
      font-size: 1.25rem;
      font-weight: 600;
      margin-bottom: 0.5rem;
      color: var(--text);
      line-height: 1.4;
    }

    .workflow-description {
      color: var(--text-secondary);
      margin-bottom: 1rem;
      line-height: 1.5;
    }

    .workflow-integrations {
      margin-top: 1rem;
    }

    .integrations-title {
      font-size: 0.875rem;
      font-weight: 500;
      color: var(--text-secondary);
      margin-bottom: 0.5rem;
    }

    .integrations-list {
      display: flex;
      flex-wrap: wrap;
      gap: 0.25rem;
    }

    .integration-tag {
      background: var(--bg-tertiary);
      color: var(--text-secondary);
      padding: 0.125rem 0.5rem;
      border-radius: 0.25rem;
      font-size: 0.75rem;
      border: 1px solid var(--border);
    }

    .workflow-actions {
      display: flex;
      gap: 0.5rem;
      margin-top: 1rem;
      padding-top: 1rem;
      border-top: 1px solid var(--border);
    }

    .action-btn {
      padding: 0.5rem 1rem;
      border: 1px solid var(--border);
      border-radius: 0.375rem;
      background: var(--bg);
      color: var(--text);
      text-decoration: none;
      font-size: 0.875rem;
      font-weight: 500;
      cursor: pointer;
      transition: all 0.2s ease;
    }

    .action-btn:hover {
      background: var(--bg-tertiary);
      border-color: var(--primary);
    }

    .action-btn.primary {
      background: var(--primary);
      color: white;
      border-color: var(--primary);
    }

    .action-btn.primary:hover {
      background: var(--primary-dark);
    }

    /* Load More */
    .load-more {
      text-align: center;
      margin-top: 2rem;
    }

    .load-more-btn {
      background: var(--primary);
      color: white;
      border: none;
      padding: 0.75rem 2rem;
      border-radius: 0.5rem;
      cursor: pointer;
      font-size: 1rem;
      font-weight: 500;
    }

    .load-more-btn:hover {
      background: var(--primary-dark);
    }

    /* Modal */
    .modal {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(0, 0, 0, 0.5);
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 1000;
      padding: 1rem;
    }

    .modal-content {
      background: var(--bg);
      border-radius: 0.75rem;
      max-width: 800px;
      width: 100%;
      max-height: 90vh;
      overflow-y: auto;
      position: relative;
    }

    .modal-header {
      padding: 1.5rem;
      border-bottom: 1px solid var(--border);
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .modal-title {
      font-size: 1.25rem;
      font-weight: 600;
    }

    .modal-close {
      background: none;
      border: none;
      font-size: 1.5rem;
      cursor: pointer;
      padding: 0.25rem;
      color: var(--text-secondary);
    }

    .modal-body {
      padding: 1.5rem;
    }

    .workflow-detail {
      margin-bottom: 1rem;
    }

    .workflow-detail h4 {
      font-size: 0.875rem;
      font-weight: 600;
      color: var(--text-secondary);
      text-transform: uppercase;
      letter-spacing: 0.05em;
      margin-bottom: 0.5rem;
    }

    .section-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: 0.5rem;
    }

    .copy-btn {
      background: var(--primary);
      color: white;
      border: none;
      padding: 0.25rem 0.5rem;
      border-radius: 0.25rem;
      font-size: 0.75rem;
      cursor: pointer;
      transition: all 0.2s ease;
      display: flex;
      align-items: center;
      gap: 0.25rem;
    }

    .copy-btn:hover {
      background: var(--primary-dark);
    }

    .copy-btn.copied {
      background: var(--success);
    }

    .copy-btn.copied:hover {
      background: var(--success);
    }

    .json-viewer {
      background: var(--bg-secondary);
      border: 1px solid var(--border);
      border-radius: 0.5rem;
      padding: 1rem;
      font-family: 'Courier New', monospace;
      font-size: 0.875rem;
      overflow-x: auto;
      max-height: 400px;
      white-space: pre-wrap;
    }

    .hidden {
      display: none !important;
    }

    /* Mermaid diagram styling */
    .mermaid {
      background: var(--bg-secondary);
      border: 1px solid var(--border);
      border-radius: 0.5rem;
      padding: 1rem;
      text-align: center;
      overflow: visible;
      min-height: 300px;
    }

    .mermaid svg {
      max-width: none;
      height: auto;
      transition: transform 0.2s ease;
    }

    .diagram-container {
      background: var(--bg-secondary);
      border: 1px solid var(--border);
      border-radius: 0.5rem;
      padding: 1rem;
      text-align: center;
      overflow: hidden;
      height: 500px;
      position: relative;
      cursor: grab;
      user-select: none;
    }

    .diagram-container.dragging {
      cursor: grabbing;
    }

    .diagram-container .mermaid {
      border: none;
      background: transparent;
      padding: 0;
    }

    .diagram-controls {
      display: flex;
      align-items: center;
      gap: 0.5rem;
    }

    .zoom-btn {
      background: var(--bg-tertiary);
      color: var(--text);
      border: 1px solid var(--border);
      border-radius: 0.25rem;
      padding: 0.25rem 0.5rem;
      font-size: 0.75rem;
      cursor: pointer;
      transition: all 0.2s ease;
      display: flex;
      align-items: center;
      gap: 0.25rem;
      min-width: 32px;
      height: 32px;
      justify-content: center;
    }

    .zoom-btn:hover {
      background: var(--primary);
      color: white;
      border-color: var(--primary);
    }

    .zoom-btn:active {
      transform: scale(0.95);
    }

    .zoom-info {
      font-size: 0.75rem;
      color: var(--text-secondary);
      margin-left: 0.5rem;
    }

    /* Responsive */
    @media (max-width: 768px) {
      .title {
        font-size: 2rem;
      }

      .stats {
        gap: 1rem;
      }

      .search-section,
      .filter-section {
        flex-direction: column;
        align-items: stretch;
      }

      .search-input {
        min-width: auto;
      }

      .theme-toggle {
        margin-left: 0;
        align-self: flex-start;
      }

      .workflow-grid {
        grid-template-columns: 1fr;
      }

      .workflow-header {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.5rem;
      }
    }
  </style>
</head>

<body>
  <div id="app">
    <!-- Header -->
    <header class="header">
      <div class="container">
        <h1 class="title">⚡ N8N Workflow Documentation</h1>
        <p class="subtitle">Lightning-fast workflow browser with instant search</p>
        <div class="stats">
          <div class="stat">
            <span class="stat-number" id="totalCount">0</span>
            <span class="stat-label">Total</span>
          </div>
          <div class="stat">
            <span class="stat-number" id="activeCount">0</span>
            <span class="stat-label">Active</span>
          </div>
          <div class="stat">
            <span class="stat-number" id="nodeCount">0</span>
            <span class="stat-label">Total Nodes</span>
          </div>
          <div class="stat">
            <span class="stat-number" id="integrationCount">0</span>
            <span class="stat-label">Integrations</span>
          </div>
        </div>
      </div>
    </header>

    <!-- Controls -->
    <div class="controls">
      <div class="container">
        <div class="search-section">
          <input type="text" id="searchInput" class="search-input"
            placeholder="Search workflows by name, description, or integration...">
        </div>

        <div class="filter-section">
          <div class="filter-group">
            <label for="triggerFilter">Trigger:</label>
            <select id="triggerFilter">
              <option value="all">All Types</option>
              <option value="Webhook">Webhook</option>
              <option value="Scheduled">Scheduled</option>
              <option value="Manual">Manual</option>
              <option value="Complex">Complex</option>
            </select>
          </div>

          <div class="filter-group">
            <label for="complexityFilter">Complexity:</label>
            <select id="complexityFilter">
              <option value="all">All Levels</option>
              <option value="low">Low (≤5 nodes)</option>
              <option value="medium">Medium (6-15 nodes)</option>
              <option value="high">High (16+ nodes)</option>
            </select>
          </div>

          <div class="filter-group">
            <label for="categoryFilter">Category:</label>
            <select id="categoryFilter">
              <option value="all">All Categories</option>
              <!-- Categories will be populated dynamically -->
            </select>
          </div>

          <div class="filter-group">
            <label>
              <input type="checkbox" id="activeOnly">
              Active only
            </label>
          </div>

          <button id="themeToggle" class="theme-toggle">🌙</button>
        </div>

        <div class="results-info">
          <span id="resultsCount">Loading...</span>
        </div>
      </div>
    </div>

    <!-- Main Content -->
    <main class="main">
      <div class="container">
        <!-- Loading State -->
        <div id="loadingState" class="state loading">
          <div class="icon">⚡</div>
          <h3>Loading workflows...</h3>
          <p>Please wait while we fetch your workflow data</p>
        </div>

        <!-- Error State -->
        <div id="errorState" class="state error hidden">
          <div class="icon">❌</div>
          <h3>Error Loading Workflows</h3>
          <p id="errorMessage">Something went wrong. Please try again.</p>
          <button id="retryBtn" class="retry-btn">Retry</button>
        </div>

        <!-- No Results State -->
        <div id="noResultsState" class="state hidden">
          <div class="icon">🔍</div>
          <h3>No workflows found</h3>
          <p>Try adjusting your search terms or filters</p>
        </div>

        <!-- Workflows Grid -->
        <div id="workflowGrid" class="workflow-grid hidden">
          <!-- Workflow cards will be inserted here -->
        </div>

        <!-- Load More -->
        <div id="loadMoreContainer" class="load-more hidden">
          <button id="loadMoreBtn" class="load-more-btn">Load More</button>
        </div>
      </div>
    </main>

    <!-- Workflow Detail Modal -->
    <div id="workflowModal" class="modal hidden">
      <div class="modal-content">
        <div class="modal-header">
          <h2 class="modal-title" id="modalTitle">Workflow Details</h2>
          <button class="modal-close" id="modalClose">&times;</button>
        </div>
        <div class="modal-body">
          <div class="workflow-detail">
            <h4>Description</h4>
            <p id="modalDescription">Loading...</p>
          </div>

          <div class="workflow-detail">
            <h4>Statistics</h4>
            <div id="modalStats">Loading...</div>
          </div>

          <div class="workflow-detail">
            <h4>Integrations</h4>
            <div id="modalIntegrations">Loading...</div>
          </div>

          <div class="workflow-detail">
            <h4>Actions</h4>
            <div class="workflow-actions">
              <a id="downloadBtn" class="action-btn primary" href="#" download>📥 Download JSON</a>
              <button id="viewJsonBtn" class="action-btn">📄 View JSON</button>
              <button id="viewDiagramBtn" class="action-btn">📊 View Diagram</button>
            </div>
          </div>

          <div class="workflow-detail hidden" id="jsonSection">
            <div class="section-header">
              <h4>Workflow JSON</h4>
              <button id="copyJsonBtn" class="copy-btn" title="Copy JSON to clipboard">
                📋 Copy
              </button>
            </div>
            <div class="json-viewer" id="jsonViewer">Loading...</div>
          </div>

          <div class="workflow-detail hidden" id="diagramSection">
            <div class="section-header">
              <h4>Workflow Diagram</h4>
              <div class="diagram-controls">
                <button id="zoomInBtn" class="zoom-btn" title="Zoom In">🔍+</button>
                <button id="zoomOutBtn" class="zoom-btn" title="Zoom Out">🔍-</button>
                <button id="zoomResetBtn" class="zoom-btn" title="Reset Zoom">🔄</button>
                <button id="copyDiagramBtn" class="copy-btn" title="Copy diagram code to clipboard">
                  📋 Copy
                </button>
              </div>
            </div>
            <div id="diagramContainer" class="diagram-container">
              <div id="diagramViewer">Loading diagram...</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <script>
    // Enhanced Workflow App with Full Functionality
    class WorkflowApp {
      constructor() {
        this.state = {
          workflows: [],
          currentPage: 1,
          totalPages: 1,
          totalCount: 0,
          perPage: 20,
          isLoading: false,
          searchQuery: '',
          filters: {
            trigger: 'all',
            complexity: 'all',
            category: 'all',
            activeOnly: false
          },
          categories: [],
          categoryMap: new Map()
        };

        this.elements = {
          searchInput: document.getElementById('searchInput'),
          triggerFilter: document.getElementById('triggerFilter'),
          complexityFilter: document.getElementById('complexityFilter'),
          categoryFilter: document.getElementById('categoryFilter'),
          activeOnlyFilter: document.getElementById('activeOnly'),
          themeToggle: document.getElementById('themeToggle'),
          resultsCount: document.getElementById('resultsCount'),
          workflowGrid: document.getElementById('workflowGrid'),
          loadMoreContainer: document.getElementById('loadMoreContainer'),
          loadMoreBtn: document.getElementById('loadMoreBtn'),
          loadingState: document.getElementById('loadingState'),
          errorState: document.getElementById('errorState'),
          noResultsState: document.getElementById('noResultsState'),
          errorMessage: document.getElementById('errorMessage'),
          retryBtn: document.getElementById('retryBtn'),
          totalCount: document.getElementById('totalCount'),
          activeCount: document.getElementById('activeCount'),
          nodeCount: document.getElementById('nodeCount'),
          integrationCount: document.getElementById('integrationCount'),
          // Modal elements
          workflowModal: document.getElementById('workflowModal'),
          modalTitle: document.getElementById('modalTitle'),
          modalClose: document.getElementById('modalClose'),
          modalDescription: document.getElementById('modalDescription'),
          modalStats: document.getElementById('modalStats'),
          modalIntegrations: document.getElementById('modalIntegrations'),
          downloadBtn: document.getElementById('downloadBtn'),
          viewJsonBtn: document.getElementById('viewJsonBtn'),
          viewDiagramBtn: document.getElementById('viewDiagramBtn'),
          jsonSection: document.getElementById('jsonSection'),
          jsonViewer: document.getElementById('jsonViewer'),
          diagramSection: document.getElementById('diagramSection'),
          diagramViewer: document.getElementById('diagramViewer'),
          diagramContainer: document.getElementById('diagramContainer'),
          copyJsonBtn: document.getElementById('copyJsonBtn'),
          copyDiagramBtn: document.getElementById('copyDiagramBtn'),
          zoomInBtn: document.getElementById('zoomInBtn'),
          zoomOutBtn: document.getElementById('zoomOutBtn'),
          zoomResetBtn: document.getElementById('zoomResetBtn')
        };

        this.searchDebounceTimer = null;
        this.currentWorkflow = null;
        this.currentJsonData = null;
        this.currentDiagramData = null;
        this.diagramZoom = 1;
        this.diagramSvg = null;
        this.diagramPan = { x: 0, y: 0 };
        this.isDragging = false;
        this.lastMousePos = { x: 0, y: 0 };
        this.init();
      }

      async init() {
        this.setupEventListeners();
        this.setupTheme();
        this.initMermaid();
        await this.loadInitialData();
      }

      initMermaid() {
        // Initialize Mermaid with proper configuration
        if (typeof mermaid !== 'undefined') {
          mermaid.initialize({
            startOnLoad: false,
            theme: 'base',
            themeVariables: {
              primaryColor: '#3b82f6',
              primaryTextColor: '#1e293b',
              primaryBorderColor: '#2563eb',
              lineColor: '#64748b',
              secondaryColor: '#f1f5f9',
              tertiaryColor: '#f8fafc'
            }
          });
        }
      }

      setupEventListeners() {
        // Search and filters
        this.elements.searchInput.addEventListener('input', (e) => {
          this.state.searchQuery = e.target.value;
          this.debounceSearch();
        });

        this.elements.triggerFilter.addEventListener('change', (e) => {
          this.state.filters.trigger = e.target.value;
          this.state.currentPage = 1;
          this.resetAndSearch();
        });

        this.elements.complexityFilter.addEventListener('change', (e) => {
          this.state.filters.complexity = e.target.value;
          this.state.currentPage = 1;
          this.resetAndSearch();
        });

        this.elements.categoryFilter.addEventListener('change', (e) => {
          const selectedCategory = e.target.value;
          console.log(`Category filter changed to: ${selectedCategory}`);
          console.log('Current category map size:', this.state.categoryMap.size);
          
          this.state.filters.category = selectedCategory;
          this.state.currentPage = 1;
          this.resetAndSearch();
        });

        this.elements.activeOnlyFilter.addEventListener('change', (e) => {
          this.state.filters.activeOnly = e.target.checked;
          this.state.currentPage = 1;
          this.resetAndSearch();
        });

        // Load more
        this.elements.loadMoreBtn.addEventListener('click', () => {
          this.loadMoreWorkflows();
        });

        // Retry
        this.elements.retryBtn.addEventListener('click', () => {
          this.loadInitialData();
        });

        // Theme toggle
        this.elements.themeToggle.addEventListener('click', () => {
          this.toggleTheme();
        });

        // Modal events
        this.elements.modalClose.addEventListener('click', () => {
          this.closeModal();
        });

        this.elements.workflowModal.addEventListener('click', (e) => {
          if (e.target === this.elements.workflowModal) {
            this.closeModal();
          }
        });

        this.elements.viewJsonBtn.addEventListener('click', () => {
          this.toggleJsonView();
        });

        this.elements.viewDiagramBtn.addEventListener('click', () => {
          this.toggleDiagramView();
        });

        // Copy button events
        this.elements.copyJsonBtn.addEventListener('click', () => {
          this.copyToClipboard(this.currentJsonData, 'copyJsonBtn');
        });

        this.elements.copyDiagramBtn.addEventListener('click', () => {
          this.copyToClipboard(this.currentDiagramData, 'copyDiagramBtn');
        });

        // Zoom control events
        this.elements.zoomInBtn.addEventListener('click', () => {
          this.zoomDiagram(1.2);
        });

        this.elements.zoomOutBtn.addEventListener('click', () => {
          this.zoomDiagram(0.8);
        });

        this.elements.zoomResetBtn.addEventListener('click', () => {
          this.resetDiagramZoom();
        });

        // Keyboard shortcuts
        document.addEventListener('keydown', (e) => {
          if (e.key === 'Escape') {
            this.closeModal();
          }
          
          // Zoom shortcuts when diagram is visible
          if (!this.elements.diagramSection.classList.contains('hidden')) {
            if (e.key === '+' || e.key === '=') {
              e.preventDefault();
              this.zoomDiagram(1.2);
            } else if (e.key === '-') {
              e.preventDefault();
              this.zoomDiagram(0.8);
            } else if (e.key === '0' && e.ctrlKey) {
              e.preventDefault();
              this.resetDiagramZoom();
            }
          }
        });
      }

      setupTheme() {
        const savedTheme = localStorage.getItem('theme') || 'light';
        document.documentElement.setAttribute('data-theme', savedTheme);
        this.updateThemeToggle(savedTheme);
      }

      toggleTheme() {
        const currentTheme = document.documentElement.getAttribute('data-theme');
        const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
        document.documentElement.setAttribute('data-theme', newTheme);
        localStorage.setItem('theme', newTheme);
        this.updateThemeToggle(newTheme);
      }

      updateThemeToggle(theme) {
        this.elements.themeToggle.textContent = theme === 'dark' ? '☀️' : '🌙';
      }

      debounceSearch() {
        clearTimeout(this.searchDebounceTimer);
        this.searchDebounceTimer = setTimeout(() => {
          this.state.currentPage = 1;
          this.resetAndSearch();
        }, 300);
      }

      async apiCall(endpoint, options = {}) {
        const response = await fetch(`/api${endpoint}`, {
          headers: {
            'Content-Type': 'application/json',
            ...options.headers
          },
          ...options
        });

        if (!response.ok) {
          throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }

        return response.json();
      }

      async loadInitialData() {
        this.showState('loading');

        try {
          // Load categories first, then stats and workflows
          console.log('Loading categories...');
          await this.loadCategories();
          
          console.log('Categories loaded, populating filter...');
          this.populateCategoryFilter();
          
          // Load stats and workflows in parallel
          console.log('Loading stats and workflows...');
          const [stats] = await Promise.all([
            this.apiCall('/stats'),
            this.loadWorkflows(true)
          ]);

          this.updateStatsDisplay(stats);
          console.log('Initial data loading complete');
        } catch (error) {
          console.error('Error during initial data loading:', error);
          this.showError('Failed to load data: ' + error.message);
        }
      }

      async loadCategories() {
        try {
          console.log('Loading categories from API...');
          
          // Load categories and mappings in parallel from API
          const [categoriesResponse, mappingsResponse] = await Promise.all([
            this.apiCall('/categories'),
            this.apiCall('/category-mappings')
          ]);
          
          // Set categories from API
          this.state.categories = categoriesResponse.categories || ['Uncategorized'];
          
          // Build category map from API mappings
          const categoryMap = new Map();
          const mappings = mappingsResponse.mappings || {};
          
          Object.entries(mappings).forEach(([filename, category]) => {
            categoryMap.set(filename, category || 'Uncategorized');
          });
          
          this.state.categoryMap = categoryMap;
          
          console.log(`Successfully loaded ${this.state.categories.length} categories from API:`, this.state.categories);
          console.log(`Loaded ${categoryMap.size} category mappings from API`);
          
          return { categories: this.state.categories, mappings: mappings };
        } catch (error) {
          console.error('Failed to load categories from API:', error);
          // Set default categories if loading fails
          this.state.categories = ['Uncategorized'];
          this.state.categoryMap = new Map();
          return { categories: this.state.categories, mappings: {} };
        }
      }

      populateCategoryFilter() {
        const select = this.elements.categoryFilter;
        
        if (!select) {
          console.error('Category filter element not found');
          return;
        }
        
        console.log('Populating category filter with:', this.state.categories);
        
        // Clear existing options except "All Categories"
        while (select.children.length > 1) {
          select.removeChild(select.lastChild);
        }
        
        if (this.state.categories.length === 0) {
          console.warn('No categories available to populate filter');
          return;
        }
        
        // Add categories in alphabetical order
        this.state.categories.forEach(category => {
          const option = document.createElement('option');
          option.value = category;
          option.textContent = category;
          select.appendChild(option);
          console.log(`Added category option: ${category}`);
        });
        
        console.log(`Category filter populated with ${select.options.length - 1} categories`);
      }

      async loadWorkflows(reset = false) {
        if (reset) {
          this.state.currentPage = 1;
          this.state.workflows = [];
        }

        this.state.isLoading = true;

        try {
          // If category filtering is active, we need to load all workflows to filter properly
          const needsAllWorkflows = this.state.filters.category !== 'all' && reset;
          
          let allWorkflows = [];
          let totalCount = 0;
          let totalPages = 1;
          
          if (needsAllWorkflows) {
            // Load all workflows in batches for category filtering
            console.log('Loading all workflows for category filtering...');
            allWorkflows = await this.loadAllWorkflowsForCategoryFiltering();
            
            // Apply client-side category filtering
            console.log(`Filtering ${allWorkflows.length} workflows for category: ${this.state.filters.category}`);
            console.log('Category map size:', this.state.categoryMap.size);
            
            let matchCount = 0;
            const filteredWorkflows = allWorkflows.filter(workflow => {
              const workflowCategory = this.getWorkflowCategory(workflow.filename);
              const matches = workflowCategory === this.state.filters.category;
              
              // Debug: log first few matches/non-matches
              if (matchCount < 5 || (!matches && matchCount < 3)) {
                console.log(`${workflow.filename}: ${workflowCategory} ${matches ? '===' : '!=='} ${this.state.filters.category}`);
              }
              
              if (matches) matchCount++;
              
              return matches;
            });
            
            console.log(`Filtered from ${allWorkflows.length} to ${filteredWorkflows.length} workflows`);
            allWorkflows = filteredWorkflows;
            totalCount = filteredWorkflows.length;
            totalPages = 1; // All results loaded, no pagination needed
          } else {
            // Normal pagination
            const params = new URLSearchParams({
              q: this.state.searchQuery,
              trigger: this.state.filters.trigger,
              complexity: this.state.filters.complexity,
              active_only: this.state.filters.activeOnly,
              page: this.state.currentPage,
              per_page: this.state.perPage
            });

            const response = await this.apiCall(`/workflows?${params}`);
            allWorkflows = response.workflows;
            totalCount = response.total;
            totalPages = response.pages;
          }

          if (reset) {
            this.state.workflows = allWorkflows;
            this.state.totalCount = totalCount;
            this.state.totalPages = totalPages;
          } else {
            this.state.workflows.push(...allWorkflows);
          }

          this.updateUI();

        } catch (error) {
          this.showError('Failed to load workflows: ' + error.message);
        } finally {
          this.state.isLoading = false;
        }
      }

      async loadAllWorkflowsForCategoryFiltering() {
        const allWorkflows = [];
        let currentPage = 1;
        const maxPerPage = 100; // API limit
        
        while (true) {
          const params = new URLSearchParams({
            q: this.state.searchQuery,
            trigger: this.state.filters.trigger,
            complexity: this.state.filters.complexity,
            active_only: this.state.filters.activeOnly,
            page: currentPage,
            per_page: maxPerPage
          });

          const response = await this.apiCall(`/workflows?${params}`);
          allWorkflows.push(...response.workflows);
          
          console.log(`Loaded page ${currentPage}/${response.pages} (${response.workflows.length} workflows)`);
          
          if (currentPage >= response.pages) {
            break;
          }
          
          currentPage++;
        }
        
        console.log(`Loaded total of ${allWorkflows.length} workflows for filtering`);
        return allWorkflows;
      }

      getWorkflowCategory(filename) {
        const category = this.state.categoryMap.get(filename);
        const result = category && category.trim() ? category : 'Uncategorized';
        return result;
      }

      async loadMoreWorkflows() {
        if (this.state.currentPage >= this.state.totalPages) return;

        this.state.currentPage++;
        await this.loadWorkflows(false);
      }

      resetAndSearch() {
        this.loadWorkflows(true);
      }

      updateUI() {
        this.updateResultsCount();
        this.renderWorkflows();
        this.updateLoadMoreButton();

        if (this.state.workflows.length === 0) {
          this.showState('no-results');
        } else {
          this.showState('content');
        }
      }

      updateStatsDisplay(stats) {
        this.elements.totalCount.textContent = stats.total.toLocaleString();
        this.elements.activeCount.textContent = stats.active.toLocaleString();
        this.elements.nodeCount.textContent = stats.total_nodes.toLocaleString();
        this.elements.integrationCount.textContent = stats.unique_integrations.toLocaleString();
      }

      updateResultsCount() {
        const count = this.state.totalCount;
        const query = this.state.searchQuery;
        const category = this.state.filters.category;
        
        let text = `${count.toLocaleString()} workflows`;
        
        if (query && category !== 'all') {
          text += ` found for "${query}" in "${category}"`;
        } else if (query) {
          text += ` found for "${query}"`;
        } else if (category !== 'all') {
          text += ` in "${category}"`;
        }
        
        this.elements.resultsCount.textContent = text;
      }

      renderWorkflows() {
        const html = this.state.workflows.map(workflow => this.createWorkflowCard(workflow)).join('');
        this.elements.workflowGrid.innerHTML = html;

        // Add click handlers to cards
        this.elements.workflowGrid.querySelectorAll('.workflow-card').forEach((card, index) => {
          card.addEventListener('click', () => {
            this.openWorkflowDetail(this.state.workflows[index]);
          });
        });
      }

      createWorkflowCard(workflow) {
        const statusClass = workflow.active ? 'status-active' : 'status-inactive';
        const complexityClass = `complexity-${workflow.complexity}`;
        const category = this.getWorkflowCategory(workflow.filename);

        const integrations = workflow.integrations.slice(0, 5).map(integration =>
          `<span class="integration-tag">${this.escapeHtml(integration)}</span>`
        ).join('');

        const moreIntegrations = workflow.integrations.length > 5
          ? `<span class="integration-tag">+${workflow.integrations.length - 5}</span>`
          : '';

        return `
                    <div class="workflow-card" data-filename="${workflow.filename}">
                        <div class="workflow-header">
                            <div class="workflow-meta">
                                <div class="status-dot ${statusClass}"></div>
                                <div class="complexity-dot ${complexityClass}"></div>
                                <span>${workflow.node_count} nodes</span>
                                <span class="category-badge">${this.escapeHtml(category)}</span>
                            </div>
                            <span class="trigger-badge">${this.escapeHtml(workflow.trigger_type)}</span>
                        </div>
                        
                        <h3 class="workflow-title">${this.escapeHtml(workflow.name)}</h3>
                        <p class="workflow-description">${this.escapeHtml(workflow.description)}</p>
                        
                        ${workflow.integrations.length > 0 ? `
                            <div class="workflow-integrations">
                                <h4 class="integrations-title">Integrations (${workflow.integrations.length})</h4>
                                <div class="integrations-list">
                                    ${integrations}
                                    ${moreIntegrations}
                                </div>
                            </div>
                        ` : ''}
                    </div>
                `;
      }

      async openWorkflowDetail(workflow) {
        this.currentWorkflow = workflow;
        this.elements.modalTitle.textContent = workflow.name;
        this.elements.modalDescription.textContent = workflow.description;

        // Update stats
        const category = this.getWorkflowCategory(workflow.filename);
        this.elements.modalStats.innerHTML = `
                    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1rem;">
                        <div><strong>Status:</strong> ${workflow.active ? 'Active' : 'Inactive'}</div>
                        <div><strong>Trigger:</strong> ${workflow.trigger_type}</div>
                        <div><strong>Complexity:</strong> ${workflow.complexity}</div>
                        <div><strong>Nodes:</strong> ${workflow.node_count}</div>
                        <div><strong>Category:</strong> ${this.escapeHtml(category)}</div>
                    </div>
                `;

        // Update integrations
        if (workflow.integrations.length > 0) {
          this.elements.modalIntegrations.innerHTML = workflow.integrations
            .map(integration => `<span class="integration-tag">${this.escapeHtml(integration)}</span>`)
            .join(' ');
        } else {
          this.elements.modalIntegrations.textContent = 'No integrations found';
        }

        // Set download link
        this.elements.downloadBtn.href = `/api/workflows/${workflow.filename}/download`;
        this.elements.downloadBtn.download = workflow.filename;

        // Reset view states
        this.elements.jsonSection.classList.add('hidden');
        this.elements.diagramSection.classList.add('hidden');

        this.elements.workflowModal.classList.remove('hidden');
      }

      closeModal() {
        this.elements.workflowModal.classList.add('hidden');
        this.currentWorkflow = null;
        this.currentJsonData = null;
        this.currentDiagramData = null;
        this.diagramSvg = null;
        this.diagramZoom = 1;
        this.diagramPan = { x: 0, y: 0 };
        this.isDragging = false;

        // Reset button states
        this.elements.viewJsonBtn.textContent = '📄 View JSON';
        this.elements.viewDiagramBtn.textContent = '📊 View Diagram';

        // Reset copy button states
        this.resetCopyButton('copyJsonBtn');
        this.resetCopyButton('copyDiagramBtn');
      }

      async toggleJsonView() {
        if (!this.currentWorkflow) return;

        const isVisible = !this.elements.jsonSection.classList.contains('hidden');

        if (isVisible) {
          this.elements.jsonSection.classList.add('hidden');
          this.elements.viewJsonBtn.textContent = '📄 View JSON';
        } else {
          try {
            this.elements.jsonViewer.textContent = 'Loading...';
            this.elements.jsonSection.classList.remove('hidden');
            this.elements.viewJsonBtn.textContent = '📄 Hide JSON';

            const data = await this.apiCall(`/workflows/${this.currentWorkflow.filename}`);
            const jsonString = JSON.stringify(data.raw_json, null, 2);
            this.currentJsonData = jsonString;
            this.elements.jsonViewer.textContent = jsonString;
          } catch (error) {
            this.elements.jsonViewer.textContent = 'Error loading JSON: ' + error.message;
            this.currentJsonData = null;
          }
        }
      }

      async toggleDiagramView() {
        if (!this.currentWorkflow) return;

        const isVisible = !this.elements.diagramSection.classList.contains('hidden');

        if (isVisible) {
          this.elements.diagramSection.classList.add('hidden');
          this.elements.viewDiagramBtn.textContent = '📊 View Diagram';
        } else {
          try {
            this.elements.diagramViewer.textContent = 'Loading diagram...';
            this.elements.diagramSection.classList.remove('hidden');
            this.elements.viewDiagramBtn.textContent = '📊 Hide Diagram';

            const data = await this.apiCall(`/workflows/${this.currentWorkflow.filename}/diagram`);
            this.currentDiagramData = data.diagram;

            // Create a Mermaid diagram that will be rendered
            this.elements.diagramViewer.innerHTML = `
                            <pre class="mermaid">${data.diagram}</pre>
                        `;

            // Re-initialize Mermaid for the new diagram
            if (typeof mermaid !== 'undefined') {
              mermaid.init(undefined, this.elements.diagramViewer.querySelector('.mermaid'));
              
              // Store reference to SVG and reset zoom
              setTimeout(() => {
                this.diagramSvg = this.elements.diagramViewer.querySelector('.mermaid svg');
                this.resetDiagramZoom();
                this.setupDiagramPanning();
              }, 100);
            }
          } catch (error) {
            this.elements.diagramViewer.textContent = 'Error loading diagram: ' + error.message;
            this.currentDiagramData = null;
          }
        }
      }

      zoomDiagram(factor) {
        if (!this.diagramSvg) return;
        
        this.diagramZoom *= factor;
        this.diagramZoom = Math.max(0.1, Math.min(10, this.diagramZoom)); // Limit zoom between 10% and 1000%
        
        this.applyDiagramTransform();
      }

      resetDiagramZoom() {
        this.diagramZoom = 1;
        this.diagramPan = { x: 0, y: 0 };
        this.applyDiagramTransform();
      }

      applyDiagramTransform() {
        if (!this.diagramSvg) return;
        
        const transform = `scale(${this.diagramZoom}) translate(${this.diagramPan.x}px, ${this.diagramPan.y}px)`;
        this.diagramSvg.style.transform = transform;
        this.diagramSvg.style.transformOrigin = 'center center';
      }

      setupDiagramPanning() {
        if (!this.elements.diagramContainer) return;

        // Mouse events
        this.elements.diagramContainer.addEventListener('mousedown', (e) => {
          if (e.button === 0) { // Left mouse button
            this.startDragging(e.clientX, e.clientY);
            e.preventDefault();
          }
        });

        document.addEventListener('mousemove', (e) => {
          if (this.isDragging) {
            this.handleDragging(e.clientX, e.clientY);
            e.preventDefault();
          }
        });

        document.addEventListener('mouseup', () => {
          this.stopDragging();
        });

        // Touch events for mobile
        this.elements.diagramContainer.addEventListener('touchstart', (e) => {
          if (e.touches.length === 1) {
            const touch = e.touches[0];
            this.startDragging(touch.clientX, touch.clientY);
            e.preventDefault();
          }
        });

        document.addEventListener('touchmove', (e) => {
          if (this.isDragging && e.touches.length === 1) {
            const touch = e.touches[0];
            this.handleDragging(touch.clientX, touch.clientY);
            e.preventDefault();
          }
        });

        document.addEventListener('touchend', () => {
          this.stopDragging();
        });

        // Prevent context menu on right click
        this.elements.diagramContainer.addEventListener('contextmenu', (e) => {
          e.preventDefault();
        });

        // Mouse wheel zoom
        this.elements.diagramContainer.addEventListener('wheel', (e) => {
          e.preventDefault();
          const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1;
          this.zoomDiagram(zoomFactor);
        });
      }

      startDragging(x, y) {
        this.isDragging = true;
        this.lastMousePos = { x, y };
        this.elements.diagramContainer.classList.add('dragging');
      }

      handleDragging(x, y) {
        if (!this.isDragging) return;

        const deltaX = x - this.lastMousePos.x;
        const deltaY = y - this.lastMousePos.y;

        // Apply pan delta scaled by zoom level (inverse relationship)
        this.diagramPan.x += deltaX / this.diagramZoom;
        this.diagramPan.y += deltaY / this.diagramZoom;

        this.lastMousePos = { x, y };
        this.applyDiagramTransform();
      }

      stopDragging() {
        this.isDragging = false;
        this.elements.diagramContainer.classList.remove('dragging');
      }      updateLoadMoreButton() {
        const hasMore = this.state.currentPage < this.state.totalPages;

        if (hasMore && this.state.workflows.length > 0) {
          this.elements.loadMoreContainer.classList.remove('hidden');
        } else {
          this.elements.loadMoreContainer.classList.add('hidden');
        }
      }

      showState(state) {
        // Hide all states
        this.elements.loadingState.classList.add('hidden');
        this.elements.errorState.classList.add('hidden');
        this.elements.noResultsState.classList.add('hidden');
        this.elements.workflowGrid.classList.add('hidden');

        // Show the requested state
        switch (state) {
          case 'loading':
            this.elements.loadingState.classList.remove('hidden');
            break;
          case 'error':
            this.elements.errorState.classList.remove('hidden');
            break;
          case 'no-results':
            this.elements.noResultsState.classList.remove('hidden');
            break;
          case 'content':
            this.elements.workflowGrid.classList.remove('hidden');
            break;
        }
      }

      showError(message) {
        this.elements.errorMessage.textContent = message;
        this.showState('error');
      }

      escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
      }

      async copyToClipboard(text, buttonId) {
        if (!text) {
          console.warn('No content to copy');
          return;
        }

        try {
          await navigator.clipboard.writeText(text);
          this.showCopySuccess(buttonId);
        } catch (error) {
          // Fallback for older browsers
          this.fallbackCopyToClipboard(text, buttonId);
        }
      }

      fallbackCopyToClipboard(text, buttonId) {
        const textArea = document.createElement('textarea');
        textArea.value = text;
        textArea.style.position = 'fixed';
        textArea.style.left = '-999999px';
        textArea.style.top = '-999999px';
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();

        try {
          document.execCommand('copy');
          this.showCopySuccess(buttonId);
        } catch (error) {
          console.error('Failed to copy text: ', error);
        } finally {
          document.body.removeChild(textArea);
        }
      }

      showCopySuccess(buttonId) {
        const button = document.getElementById(buttonId);
        if (!button) return;

        const originalText = button.innerHTML;
        button.innerHTML = '✅ Copied!';
        button.classList.add('copied');

        setTimeout(() => {
          button.innerHTML = originalText;
          button.classList.remove('copied');
        }, 2000);
      }

      resetCopyButton(buttonId) {
        const button = document.getElementById(buttonId);
        if (!button) return;

        button.innerHTML = '📋 Copy';
        button.classList.remove('copied');
      }
    }

    // Initialize the app
    document.addEventListener('DOMContentLoaded', () => {
      window.workflowApp = new WorkflowApp();
    });
  </script>
</body>

</html>